//
// Created on 2024/11/30.
//
// Node APIs are not fully supported. To solve the compilation error of the interface cannot be found,
// please include "napi/native_api.h".

#ifndef SLOTDRAWING_GETRLOTTIE_H
#define SLOTDRAWING_GETRLOTTIE_H
#include "rlottie.h"
#include "ArkUINode.h"
#include <cstdint>
#include <hilog/log.h>

class Glottie {
public:
    std::unique_ptr<rlottie::Animation> player;
    int32_t totalFrame = 0;
    int32_t duration = 0;
    int32_t frameRate = 0;
    Glottie()
    {
    }

    ~Glottie()
    {
    }

    void InitFormFile(std::string file)
    {
        player = rlottie::Animation::loadFromFile(file);
    }

    void InitFormData(std::string json)
    {
//         player = rlottie::Animation::loadFromData(json);
    }

    int32_t PrintInfo()
    {
        if (!player) {
            DRAWING_LOGE("\n\n\n\n请先进行初始化");
            return -1;
        }
        totalFrame = player->totalFrame();
        duration = player->duration();
        frameRate = player->frameRate();
        DRAWING_LOGE("\n\n\n时间长度%{public}d", duration);
        DRAWING_LOGE("\n\n\n帧数%{public}d", totalFrame);
        DRAWING_LOGE("\n\n\n帧率%{public}d", frameRate);
        return 1;
    }

    void *RenderFrame(int32_t FrameNum, int32_t width, int32_t height)
    {
         auto now = std::chrono::high_resolution_clock::now();
         auto startTime = std::chrono::time_point_cast<std::chrono::nanoseconds>(now).time_since_epoch();

        auto buffer = std::unique_ptr<uint32_t[]>(new uint32_t[width * height]);
        rlottie::Surface surface(buffer.get(), width, height, width * 4);
        
        player->renderSync(FrameNum, surface);
        
        now = std::chrono::high_resolution_clock::now();
        auto endTime = std::chrono::time_point_cast<std::chrono::nanoseconds>(now).time_since_epoch();
        DRAWING_LOGE("-------------------rlottie单次解析第%{public}2.d帧,用时%{public}5.3fms", FrameNum, (endTime - startTime) / 1000000.0);

        return reinterpret_cast<void *>(surface.buffer());
    }

    void *RenderSyncFrame(int32_t FrameNum, int32_t width, int32_t height)
    {
        auto buffer = std::unique_ptr<uint32_t[]>(new uint32_t[width * height]);
        rlottie::Surface surface(buffer.get(), width, height, width * 4);
        player->renderSync(FrameNum, surface);
        return reinterpret_cast<void *>(surface.buffer());

        //         std::future<rlottie::Surface> handle = player->render(FrameNum, surface);
        //         surface = handle.get();
    }

    void *RenderFrameTorgba(int32_t FrameNum, int32_t width, int32_t height)
    {
//         auto now = std::chrono::high_resolution_clock::now();
//         auto startTime = std::chrono::time_point_cast<std::chrono::nanoseconds>(now).time_since_epoch();

        auto buffer = std::unique_ptr<uint32_t[]>(new uint32_t[width * height]);
        rlottie::Surface surface(buffer.get(), width, height, width * 4);
        player->renderSync(FrameNum, surface);
//         argbTorgba(surface);
        
//         now = std::chrono::high_resolution_clock::now();
//         auto endTime = std::chrono::time_point_cast<std::chrono::nanoseconds>(now).time_since_epoch();
//         DRAWING_LOGE("\n\n\n单次解析第%{public}d帧,用时%{public}ld",FrameNum,endTime - startTime);

        return reinterpret_cast<void *>(surface.buffer());
    }

private:
    void argbTorgba(rlottie::Surface &s)
    {
        uint8_t bgColorR, bgColorG, bgColorB;
        uint8_t *buffer = reinterpret_cast<uint8_t *>(s.buffer());
        uint32_t totalBytes = s.height() * s.bytesPerLine();
        for (uint32_t i = 0; i < totalBytes; i += 4) {
            unsigned char a = buffer[i + 3];
            // compute only if alpha is non zero
            if (a) {
                unsigned char r = buffer[i + 2];
                unsigned char g = buffer[i + 1];
                unsigned char b = buffer[i];

                if (a != 255) { // un premultiply
                    unsigned char r2 = (unsigned char)((float)bgColorR * ((float)(255 - a) / 255));
                    unsigned char g2 = (unsigned char)((float)bgColorG * ((float)(255 - a) / 255));
                    unsigned char b2 = (unsigned char)((float)bgColorB * ((float)(255 - a) / 255));
                    buffer[i] = r + r2;
                    buffer[i + 1] = g + g2;
                    buffer[i + 2] = b + b2;
                } else {
                    // only swizzle r and b
                    buffer[i] = r;
                    buffer[i + 2] = b;
                }
            } else {
                buffer[i + 2] = bgColorB;
                buffer[i + 1] = bgColorG;
                buffer[i] = bgColorR;
            }
        }
    }
};

#endif // SLOTDRAWING_GETRLOTTIE_H
